package com.iris.thread.notifyEarly;

import java.util.ArrayList;
import java.util.List;

/**
 * 项目: thinking
 * 包名: com.iris.thread.notifyEarly
 * 作者: victor
 * 日期: 2016年10月31日
 * 说明: NotifyEarly
 * threadA1和threadA2都从wait（）返回，等待获取list对象上的对象锁，并试图从列表中删除添加的元素，这就会产生麻烦，
 * 只有其中一个操作能成功。假设threadA1获取了list上的对象锁，并删除元素成功，在退出synchronized代码块时，
 * 它便会释放list上的对象锁，此时threadA2便会获取list上的对象锁，会继续删除list中的元素，但是list已经为空了，
 * 这便会抛出IndexOutOfBoundsException。
 */
public class NotifyEarly {

	public static void main(String[] args) throws InterruptedException {
		List<String> list = new ArrayList<String>();
		NotifyEarlyRunnable rm1=new NotifyEarlyRunnable(list, true);
		NotifyEarlyRunnable rm2=new NotifyEarlyRunnable(list, true);
		NotifyEarlyRunnable add=new NotifyEarlyRunnable(list, false);
		//启动第一个删除元素的线程  
        Thread threadA1 = new Thread(rm1, "rm1");  
        threadA1.start();  

        Thread.sleep(500);  
  
        //启动第二个删除元素的线程  
        Thread threadA2 = new Thread(rm2, "rm2");  
        threadA2.start();  

        Thread.sleep(500);  
        //启动增加元素的线程  
        Thread threadB = new Thread(add, "add");  
        threadB.start();  

        Thread.sleep(3000);  
	}
}

class NotifyEarlyRunnable implements Runnable{
	private List<String> list;
	private boolean removeFlag=true;
	public NotifyEarlyRunnable(List<String> list,boolean removeFlag){
		this.list=list;
		this.removeFlag=removeFlag;
	}

	@Override
	public void run() {
		if(removeFlag){
			synchronized (list) {
				if ( list.isEmpty() ) {// 要避免同时唤醒,remove时为空的错误,只需将wait外围的if语句改为while循环即可
//				while ( list.isEmpty() ) {
					try {
						list.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				list.remove(0);
			}
		}else{
			synchronized (list) {
				list.add("===");
				list.notifyAll();
			}
		}
		
	}
	
}